﻿using RakutenProxy.Model.Rakuten;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace RakutenProxy.AttributeParser
{
    public class AttributeCombination
    {
        /// <summary>
        /// The attribute that is arranged at the x-axis of the matrix
        /// </summary>
        public Attribute AttributeX { get; set; }

        /// <summary>
        /// The attribute that is arranged at the y-axis of the matrix
        /// </summary>
        public Attribute AttributeY { get; set; }

        /// <summary>
        /// Two dimension array that used to indicate whether the combination of product's attribute is on hand
        /// </summary>
        public AttributeValue[,] AvailableStatuses { get; set; }

        public List<Attribute> OtherAttributes { get; set; }

        public AttributeCombination(Attribute attributeX, Attribute attributeY)
        {
            this.AttributeX = attributeX;
            this.AttributeY = attributeY;
            AvailableStatuses = new AttributeValue[AttributeX.AttributeValues.Count, AttributeY.AttributeValues.Count];
            OtherAttributes = new List<Attribute>();
        }

        public AttributeCombination()
        {
            OtherAttributes = new List<Attribute>();
        }

        public void InitCombinationArray()
        {
            var columns = AttributeX == null || AttributeX.AttributeValues.Count == 0 ? 1 : AttributeX.AttributeValues.Count;
            var rows = AttributeY == null || AttributeY.AttributeValues.Count == 0 ? 1 : AttributeY.AttributeValues.Count;
            
            AvailableStatuses = new AttributeValue[rows, columns];
        }

        /// <summary>
        /// Get possible records of product attribute combination to add to the db
        /// </summary>
        /// <param name="productId"></param>
        /// <returns></returns>
        public IEnumerable<ProductAttributeCombination> GetProductCombinationRecords(int productId, ProductAttribute attributeX, ProductAttribute attributeY)
        {           
            var combinationsList = new List<ProductAttributeCombination>();

            if (AvailableStatuses == null)
                return combinationsList;

            var rows = this.AvailableStatuses.GetLength(0);
            var columns = this.AvailableStatuses.GetLength(1);
            for (int i = 0; i < rows; i++)
            {
                var root = new XElement("Attributes");
                
                if (attributeY != null && attributeY.ProductAttributeValues.Count > 0)
                {
                    if (attributeY.ProductAttributeId == 0)
                        throw new InvalidOperationException("The attribute has not been added to the db");

                    var attributeNode = new XElement("ProductVariantAttribute", new XAttribute("ID", attributeY.ProductAttributeId));

                    var value = attributeY.ProductAttributeValues.ElementAt(i);
                    var valueNode = new XElement("ProductVariantAttributeValue", new XElement("Value", value.Id));
                    attributeNode.Add(valueNode);
                    root.Add(attributeNode);
                }

                for (int j = 0; j < columns; j++)
                {
                    var combination = new ProductAttributeCombination { ProductId = productId };

                    XElement attributeNode = null;
                    if (attributeX != null && attributeX.ProductAttributeValues.Count > 0)
                    {
                        if (attributeX.ProductAttributeId == 0)
                            throw new InvalidOperationException("The attribute has not been added to the db");

                        attributeNode = new XElement("ProductVariantAttribute", new XAttribute("ID", attributeX.ProductAttributeId));

                        var value = attributeX.ProductAttributeValues.ElementAt(j);
                        var valueNode = new XElement("ProductVariantAttributeValue", new XElement("Value", value.Id));
                        attributeNode.Add(valueNode);
                        root.Add(attributeNode);
                    }

                    if (AvailableStatuses[i, j] != null)
                    {
                        root.Add(new XAttribute("FormValue", AvailableStatuses[i, j].ActualValue));
                        combination.IsStockAvailable = true;
                    }
                    else
                        combination.IsStockAvailable = false;

                    combination.AttributesXml = root.ToString(SaveOptions.DisableFormatting);
                    combinationsList.Add(combination);

                    if (attributeNode != null)
                        attributeNode.Remove();
                    root.RemoveAttributes();
                }                
            }

            return combinationsList;
        }
    }
}
